package nnet2.learning;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import nnet2.gui.PlotPanel;
import nnet2.net.RMLP;

public class StackLearning {

    private RMLP nnet;
    private File dataFile;
    private ArrayList<Double> data;

    public ArrayList<Double> getData() {
        return data;
    }

    public void setData(ArrayList<Double> data) {
        this.data = data;
    }

    public StackLearning(RMLP nnet, String file) {
        this.nnet = nnet;
        dataFile = new File(file);
        loadStackData();
    }

    public void train(int times) {
        for (int i = 0; i < times; i++) {
            System.out.format("iteration %d ", i);
            this.nnet.train(data, 0.000001f);
        }
    }

    public void visualTrain(int times) {
        this.nnet.train(data, 0.000001f);
        PlotPanel p = PlotPanel.showPlot(data, resArray());

        for (int i = 0; i < times; i++) {
            System.out.format("iteration %d ", i);
            p.setError(this.nnet.train(data, 0.000001f));
            p.setForcast(resArray());
            p.setIteration(i);
            //p.setError(i)
            p.repaint();
        }
    }

    public double test() {
        double err, tot = 0;
        for (int i = 0; i < data.size() - 1; i++) {
            err = data.get(i + 1) - nnet.calculateValues(new double[]{data.get(i)})[0];
            //System.out.format("e =\t%+.5f\n", err);
            tot += Math.abs(err);
        }
        return tot / data.size();
    }

    public void visualRep() {
        ArrayList<Double> result = resArray();
        PlotPanel.showPlot(data, result);
    }

    private ArrayList<Double> resArray() {
        ArrayList<Double> result = new ArrayList<Double>(data.size());
        for (int i = 0; i < data.size(); i++) {
            result.add(nnet.calculateValues(new double[]{data.get(i)})[0]);
        }
        return result;
    }

    private boolean loadStackData() {
        FileReader r;
        BufferedReader buf;
        String line;
        ArrayList<Double> data = new ArrayList<Double>();
        try {
            r = new FileReader(dataFile);
            buf = new BufferedReader(r);

            while ((line = buf.readLine()) != null) {
                try {
                    float f = Float.parseFloat(line);
                    data.add((double)f);
                } catch (NumberFormatException ne) {
                    System.out.format("Line %s was not recognised as double", line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        this.data = data;
        return true;
    }
}
